package shiyl.use.springboot.loadbalance.impl;

import shiyl.use.springboot.loadbalance.AbstractLoadBalancePolicy;
import shiyl.use.springboot.loadbalance.ILoader;
import shiyl.use.springboot.loadbalance.POLICY;

import java.util.List;
import java.util.Random;

/**
 * 随机策略
 * 权重越大，分担越多的流量
 * RandomLoadBalance 实现很简单，如果每个提供者的权重都相同，那么根据列表长度直接随机选取一个，
 * 如果权重不同，累加权重值。根据0~累加的权重值 选取一个随机数，然后判断该随机数落在那个提供者上。
 * @author  duboo
 */
public class RandomPolicy extends AbstractLoadBalancePolicy {

    private final Random random = new Random();

    /**
     * 执行随机负载策略选择负载点并返回
     *
     * @param loaders
     * @return
     */
    @Override
    protected <T> ILoader<T> doPolicySelect(List<ILoader<T>> loaders) {
        //总个数
        int length = loaders.size() ;
        //总权重
        int totalWeight = 0 ;
        //权重都一样
        boolean sameWeight = true ;
        for( int i = 0 ; i < length ; i ++ ){
           int weight = loaders.get(i) .getWeight() ;
           //累计总权重
           totalWeight += weight ;
            // 计算，是否所有权重都一样
           if( sameWeight && i > 0 && weight != loaders.get(i-1).getWeight() ){
               sameWeight = false ;
           }
        }

        if( totalWeight > 0 && ! sameWeight ){
            // 如果权重不相同且权重大于0，则按总权重数随机
            int offset = random.nextInt(totalWeight);
            // 并确定随机值落在那个片段上
            for( int i = 0 ; i < length ; i ++ ){
                offset -= loaders.get(i).getWeight();
                if( offset < 0 ){
                    return loaders.get(i);
                }
            }
        }

        // 如果权重相同或权重为0，则均等随机
        return loaders.get(random.nextInt(length));
    }

    /**
     * 策略名称
     *
     * @return
     */
    @Override
    public POLICY getPolicyName() {
        return POLICY.RANDOM;
    }
}
